package com.shangxian.giveithome.service.impl;

import cn.hutool.core.util.StrUtil;
import com.shangxian.giveithome.code.CommonCode;
import com.shangxian.giveithome.code.ImgFeiCode;
import com.shangxian.giveithome.entity.UserDetails;
import com.shangxian.giveithome.entity.petCard.PetCardImg;
import com.shangxian.giveithome.entity.petCard.outputParam.PetCardCodeDetails;
import com.shangxian.giveithome.exception.ExceptionUtils;
import com.shangxian.giveithome.exception.ImgException;
import com.shangxian.giveithome.mapper.PetCardImgMapper;
import com.shangxian.giveithome.mapper.PetCardQrCodeMapper;
import com.shangxian.giveithome.result.Result;
import com.shangxian.giveithome.service.PetCardImgService;
import com.shangxian.giveithome.utils.RedisUtils;
import com.shangxian.giveithome.utils.ZipUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.shangxian.giveithome.properties.ImageProperties.IMG_SIZE;

/**
 * @author coderFu
 * @create 2021/5/1
 */
@Service
@Slf4j
public class PetCardImgServiceImpl implements PetCardImgService {
    private static final int BUFFER_SIZE = 2 * 1024;
    @Autowired
    private RedisUtils redisUtils;

    @Resource
    private PetCardImgMapper petCardImgMapper;

    @Resource
    private PetCardQrCodeMapper petCardQrCodeMapper;

    @Resource
    private HttpServletResponse response;

    @Resource
    private HttpServletRequest request;


    //1 让checked例外也回滚：在整个方法前加上 @Transactional(rollbackFor=Exception.class)
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PetCardImg inset(UserDetails header, Long id, MultipartFile multipartFile) {
        //检查图片的大小
        if (!checkFileSize(multipartFile.getSize(), IMG_SIZE,"M")){
            ExceptionUtils.error(ImgFeiCode.FILE_SIZE);
        }
        String src_file_name = multipartFile.getOriginalFilename();
        String[] strArray = src_file_name.split("\\.");
        String ext_name = strArray[strArray.length-1];
        String file_name = strArray[0];
        byte[] bytes = null;
        try{
            bytes = multipartFile.getBytes();
        }catch (IOException e){
            log.error("【获取文件异常】");
            ExceptionUtils.error(ImgFeiCode.UPLOAD_ERROR);
        }
        String filePath = uploadFile(bytes, ext_name, file_name);
        if (StringUtils.isBlank(filePath)){
            log.error("【上传异常】");
            ExceptionUtils.error(ImgFeiCode.UPLOAD_ERROR);
        }
        PetCardImg petCardImg = new PetCardImg();
        petCardImg.setUserId(header.getId());
        petCardImg.setPath(filePath);
        if (id !=null){
            petCardImg.setKeyId(id);
            petCardImgMapper.saveByKeyId(petCardImg);
        }else{
            petCardImgMapper.save(petCardImg);
        }
        Long aLong = petCardImgMapper.queryByIds(petCardImg.getId());
        petCardImg.setKeyId(aLong);
        return petCardImg;
    }

    @Override
    public Result delete(UserDetails header, List<PetCardImg> petCardImgs) {
        if (CollectionUtils.isEmpty(petCardImgs)){
            //数据为空
            return Result.error(ImgFeiCode.FILE_NOT_NULL);
        }
        for (PetCardImg petCardImg:petCardImgs){
            if (!petCardImg.getUserId().equals(header.getId())){
                //用户不匹配，防止错误删除信息
                return Result.error(ImgFeiCode.USER_NOT_PRE);
            }
        }
        List<Long> imgIds = petCardImgs.stream().map(PetCardImg::getId).collect(Collectors.toList());
        //删除数据库中存储的记录
        petCardImgMapper.deleteById(imgIds);
        //删除服务器中存储的文件
        deletes(petCardImgs);
        return Result.success(CommonCode.DELETE_SUCCESS);
    }

    @Override
    public void downloadQrCode(List<Integer> list) throws IOException {
        System.out.println(list);
        List<PetCardCodeDetails> petCardDetailsList = petCardQrCodeMapper.findQrCodeByIds(list);
        System.out.println(petCardDetailsList);
        log.info(petCardDetailsList+"共查到多少图");
        List<File> fileList = new ArrayList<>();
        petCardDetailsList.forEach(a->{
            try {
                String realPath = request.getSession().getServletContext().getRealPath("")+"/tempQrImg";
                File f1 = new File(realPath);
                if (!f1.exists()) {
                    f1.mkdirs();
                }
                InputStream is = download(a.getPath());
                assert is != null;
                BufferedInputStream bis = new BufferedInputStream(is);
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(f1,a.getPetCardNo()+".png")));
                byte[] buffer =  new byte[BUFFER_SIZE];
                int len;
                while((len = bis.read(buffer))!=-1){
                    bos.write(buffer,0,len);
                }
                bos.flush();
                fileList.add(new File(f1+"/"+a.getPetCardNo()+".png"));
            }catch (IOException e){
                log.info("第"+a.getPetCardNo()+"宠牌二维码下载异常");
            }
        });
        BufferedOutputStream bos = null;
        response.setContentType("application/x-zip-compressed");
        response.addHeader("Content-disposition", "attachment;filename=" + "petCard1"+ ".zip");
        bos = new BufferedOutputStream(response.getOutputStream());
        ZipUtils.toZip(fileList,bos);
        try {
            if (bos !=null) {
                bos.flush();
                bos.close();
            }
    }catch (IOException e){
            log.info("流关闭异常");
        }
    }

    public Result deletes(List<PetCardImg> petCardImgs){
        for (PetCardImg petCardImg : petCardImgs) {
            Boolean aBoolean = deleteFile(petCardImg.getPath());
            if (!aBoolean){
                //删除失败
                Result result = new Result(ImgFeiCode.DELETE_ERROR);
                throw new ImgException(result);
            }
        }
            return Result.error(CommonCode.DELETE_SUCCESS);
    }











    /**
     * fastdfs 上传文件
     * @param bytes
     * @param ext_Name
     * @param file_Name
     * @return
     */
    private String uploadFile(byte[] bytes, String ext_Name, String file_Name) {
        StringBuilder stringBuilder = new StringBuilder();
        try {
            ClientGlobal.initByProperties("fastdfs.properties");
            TrackerClient trackerClient = new TrackerClient();
            TrackerServer trackerServer = trackerClient.getTrackerServer();
            String storageServerIp = getStorageServerIp(trackerClient, trackerServer);
            StorageServer storageServer = getStorageServer(storageServerIp);
            StorageClient storageClient = new StorageClient(trackerServer, storageServer);
            NameValuePair[] pairs = new NameValuePair[1];
            pairs[0] = new NameValuePair(file_Name, ext_Name);
            String[] strings = storageClient.upload_file(bytes, ext_Name, null);
            stringBuilder.append(StrUtil.join("/", (Object) strings));
        } catch (IOException | MyException e) {
            ExceptionUtils.error(ImgFeiCode.UPLOAD_ERROR);
        }
        return stringBuilder.toString();
    }




    /**
     * 删除文件
     *
     * @param filePath
     * @return
     */
    private Boolean deleteFile(String filePath) {
        try {
            // 链接FastDFS服务器，创建tracker和Stroage
            ClientGlobal.initByProperties("fastdfs.properties");
            TrackerClient trackerClient = new TrackerClient();
            TrackerServer trackerServer = trackerClient.getTrackerServer();
            String storageServerIp = getStorageServerIp(trackerClient, trackerServer);
            StorageServer storageServer = getStorageServer(storageServerIp);
            StorageClient storageClient = new StorageClient(trackerServer, storageServer);
            int i = storageClient.delete_file("group1", StringUtils.substringAfter(filePath, "group1/"));
            log.info(String.valueOf(i));
            if (i != 0) {
                log.info("删除失败");
                return false;
            }
        } catch (Exception e) {
            log.error("删除文件异常");
            e.printStackTrace();
            return false;
        }
        return true;
    }

    private static InputStream download( String fileId) {
        try {
            // 链接FastDFS服务器，创建tracker和Stroage
            ClientGlobal.initByProperties("fastdfs.properties");
            TrackerClient trackerClient = new TrackerClient();
            TrackerServer trackerServer = trackerClient.getTrackerServer();
            String storageServerIp = getStorageServerIp(trackerClient, trackerServer);
            StorageServer storageServer = getStorageServer(storageServerIp);
            StorageClient storageClient = new StorageClient(trackerServer, storageServer);
            byte[] bytes = storageClient.download_file("group1",  StringUtils.substringAfter(fileId, "group1/"));
            return new ByteArrayInputStream(bytes);
        } catch (Exception e) {
            log.error("下载文件异常");
            e.printStackTrace();
        }
        return null;
    }







    /**
     * 获得可用的storage IP
     *
     * @param trackerClient
     * @param trackerServer
     * @return 返回storage IP
     */
    private static String getStorageServerIp(TrackerClient trackerClient, TrackerServer trackerServer) {
        String storageIp = null;
        if (trackerClient != null && trackerServer != null) {
            try {
                StorageServer storageServer = trackerClient.getStoreStorage(trackerServer, "group1");
                storageIp = storageServer.getInetSocketAddress().getAddress().getHostAddress();
            } catch (IOException | MyException e) {
                e.printStackTrace();
            }
        }
        return storageIp;
    }

    /**
     * 得到Storage服务
     *
     * @param storageIp
     * @return 返回Storage服务
     */
    private static StorageServer getStorageServer(String storageIp) {
        StorageServer storageServer = null;
        if (storageIp != null && !("").equals(storageIp)) {
            try {
                // ip port store_path下标
                storageServer = new StorageServer(storageIp, 23000, 0);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return storageServer;
    }





    /**
     * 文件大小限制
     *
     * @param len
     * @param size
     * @param unit
     * @return
     */
    private static boolean checkFileSize(Long len, int size, String unit) {
        double fileSize = 0;
        if ("B".equals(unit.toUpperCase())) {
            fileSize = (double) len;
        } else if ("K".equals(unit.toUpperCase())) {
            fileSize = (double) len / 1024;
        } else if ("M".equals(unit.toUpperCase())) {
            fileSize = (double) len / 1048576;
        } else if ("G".equals(unit.toUpperCase())) {
            fileSize = (double) len / 1073741824;
        }
        if (fileSize > size) {
            return false;
        }
        return true;
    }
}
